#ifndef __System_Array_H__
#define __System_Array_H__

///<summary>
/// Array<T>
///</summary>
//+ requires: Collections_IEnumerable(T)
//+ requires: Collections_IEnumerator(T)
//+ requires: System_ArrayXSZArrayEnumerator(T)
#define System_Array(T) bindT(System_Array,T)
#define Declare_System_Array(T, Ti) \
	internal classT(System_Array,T,System_Object,classInterface(Collections_IEnumerable(T)), \
		private Ti *_array; \
	); \
	Declare_CtorT(,system,System_Array,T, Array array)
#define Implement_System_Array(T, Ti) \
	/*[ GetEnumerator ] */ \
	public Collections_IEnumerator(T) *spaceT(System_Array,T,GetEnumerator)(System_Array(T) *t) \
	{ \
		System_ArrayXSZArrayEnumerator(T) *arrayEnumerator = new(,System_ArrayXSZArrayEnumerator(T), t->_array); \
		return as(arrayEnumerator, Collections_IEnumerator(T)); \
	} \
	Implement_TypeT(System_Array,T,System_Object,typeInterface(Collections_IEnumerable(T)), \
		System_ObjectVector *vtable = t->Collections_IEnumerable(T).__vtable; \
		vtable[_Collections_IEnumerable_##T##VIndex_GetEnumerator] = (System_ObjectVector)&spaceT(System_Array,T,GetEnumerator); \
	) \
	Implement_CtorT(,System_Array,T, \
		baseCtor(,t,System_Object); \
		t->_array = (Ti *)array; \
	, Array array)

/* Forward-declare */
public static_ void space(System_Array,Clear)(Array array, int_ index, int_ length);
public static_ void space(System_Array,Copy)(Array sourceArray, Array destinationArray, int_ length);
public static_ void space(System_Array,Copy2)(Array sourceArray, Array destinationArray, long_ length);
public static_ void space(System_Array,Copy3)(Array sourceArray, int_ sourceIndex, Array destinationArray, int_ destinationIndex, int_ length);
public static_ void space(System_Array,Copy4)(Array sourceArray, long_ sourceIndex, Array destinationArray, long_ destinationIndex, long_ length);
//public static_ void space(System_Array,IndexOf)(Array sourceArray, Array destinationArray, int_ length);
//public static_ void space(System_Array,IndexOf2)(Array sourceArray, Array destinationArray, long_ length);
//public static_ void space(System_Array,IndexOf3)(Array sourceArray, int_ sourceIndex, Array destinationArray, int_ destinationIndex, int_ length);
public static_ void space(System_Array,Reverse)(Array array);
public static_ void space(System_Array,Reverse2)(Array array, int_ index, int_ length);
//+
extern static_ bool TrySZSort(Array keys, Array items, int_ left, int_ right);

//+ Generic-Method Definitions
///<summary>
/// IndexOf
///</summary>
//+ requires: Collections_IEqualityComparer(T)
//+ requires: Collections_EqualityComparer(T)
#define Declare_System_Array_IndexOf(T, Ti) \
	/* Forward-declare */ \
	public static_ int_ space_T(System_Array,IndexOf,T)(Ti array[], Ti value); \
	public static_ int_ space_T(System_Array,IndexOf2,T)(Ti array[], Ti value, int_ startIndex); \
	public static_ int_ space_T(System_Array,IndexOf3,T)(Ti array[], Ti value, int_ startIndex, int_ count);
#define Implement_System_Array_IndexOf(T, Ti) \
	/*[ IndexOf<T> ] */ \
	public static_ int_ space_T(System_Array,IndexOf,T)(Ti array[], Ti value) \
	{ \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		return space_T(System_Array,IndexOf3,T)(array, value, 0, array_getLength(array)); \
	} \
	/*[ IndexOf2<T> ] */ \
	public static_ int_ space_T(System_Array,IndexOf2,T)(Ti array[], Ti value, int_ startIndex) \
	{ \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		return space_T(System_Array,IndexOf3,T)(array, value, startIndex, array_getLength(array) - startIndex); \
	} \
	/*[ IndexOf3<T> ] */ \
	public static_ int_ space_T(System_Array,IndexOf3,T)(Ti array[], Ti value, int_ startIndex, int_ count) \
	{ \
		Collections_EqualityComparer(T) *comparer; \
		int_ arrayLength; \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		arrayLength = array_getLength(array); \
		if ((startIndex < 0) || (startIndex > arrayLength)) \
		{ \
			throw(ArgumentOutOfRangeException, L"startIndex"); \
		} \
		if ((count < 0) || (count > (arrayLength - startIndex))) \
		{ \
			throw(ArgumentOutOfRangeException, L"count"); \
		} \
		comparer = getsT(Collections_EqualityComparer,T,Default); \
		return vcallT(Collections_EqualityComparer,T,comparer,IndexOf, array, value, startIndex, count); \
	}

///<summary>
/// IndexOf
///</summary>
//+ requires: Collections_IEqualityComparer(T)
//+ requires: Collections_EqualityComparer(T)
#define Declare_System_Array_LastIndexOf(T, Ti) \
	/* Forward-declare */ \
	public static_ int_ space_T(System_Array,LastIndexOf,T)(Ti array[], Ti value); \
	public static_ int_ space_T(System_Array,LastIndexOf2,T)(Ti array[], Ti value, int_ startIndex); \
	public static_ int_ space_T(System_Array,LastIndexOf3,T)(Ti array[], Ti value, int_ startIndex, int_ count);
#define Implement_System_Array_LastIndexOf(T, Ti) \
	/*[ LastIndexOf<T> ] */ \
	public static_ int_ space_T(System_Array,LastIndexOf,T)(Ti array[], Ti value) \
	{ \
		int_ arrayLength; \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		arrayLength = array_getLength(array); \
		return space_T(System_Array,LastIndexOf3,T)(array, value, arrayLength - 1, arrayLength); \
	} \
	/*[ LastIndexOf2<T> ] */ \
	public static_ int_ space_T(System_Array,LastIndexOf2,T)(Ti array[], Ti value, int_ startIndex) \
	{ \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		return space_T(System_Array,LastIndexOf3,T)(array, value, startIndex, (array_getLength(array) == 0 ? 0 : startIndex + 1)); \
	} \
	/*[ LastIndexOf3<T> ] */ \
	public static_ int_ space_T(System_Array,LastIndexOf3,T)(Ti array[], Ti value, int_ startIndex, int_ count) \
	{ \
		Collections_EqualityComparer(T) *comparer; \
		int_ arrayLength; \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		arrayLength = array_getLength(array); \
		if (arrayLength == 0) \
		{ \
			if ((startIndex != -1) && (startIndex != 0)) \
			{ \
				throw(ArgumentOutOfRangeException, L"startIndex"); \
			} \
			if (count != 0) \
			{ \
				throw(ArgumentOutOfRangeException, L"count"); \
			} \
			return -1; \
		} \
		if ((startIndex < 0) || (startIndex >= arrayLength)) \
		{ \
			throw(ArgumentOutOfRangeException, L"startIndex"); \
		} \
		if ((count < 0) || (((startIndex - count) + 1) < 0)) \
		{ \
			throw(ArgumentOutOfRangeException, L"count"); \
		} \
		comparer = getsT(Collections_EqualityComparer,T,Default); \
		return vcallT(Collections_EqualityComparer,T,comparer,LastIndexOf, array, value, startIndex, count); \
	}


///<summary>
/// BinarySearch<T>
///</summary>
//+ requires: Collections_IComparer(T)
#define Declare_System_Array_BinarySearch(T, Ti) \
	/* Forward-declare */ \
	public static_ int_ space_T(System_Array,BinarySearch,T)(Ti array[], int_ index, int_ length, Ti value, Collections_IComparer(T) *comparer);
#define Implement_System_Array_BinarySearch(T, Ti) \
	/*[ BinarySearch<T> ] */ \
	public static_ int_ space_T(System_Array,BinarySearch,T)(Ti array[], int_ index, int_ length, Ti value, Collections_IComparer(T) *comparer) \
	{ \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		if ((index < 0) || (length < 0)) \
		{ \
			throw(ArgumentOutOfRangeException, (index < 0 ? L"index" : L"length")); \
		} \
		if ((array_getLength(array) - index) < length) \
		{ \
			throw(ArgumentException, L"Argument_InvalidOffLen"); \
		} \
		return 0; \
	}
	//return ArraySortHelper<T>.Default.BinarySearch(array, index, length, value, comparer);


///<summary>
/// Sort<T>
///</summary>
//+ requires: System_Comparison(T)
//+ requires: Collections_IComparer(T)
//+ requires: Collections_Comparer(T)
//+ requires: System_ArrayXFunctorComparer(T)
#define Declare_System_Array_Sort(T, Ti) \
	/* Forward-declare */ \
	public static_ void space_T(System_Array,Sort,T)(Ti array[]); \
	public static_ void space_T(System_Array,Sort2,T)(Ti array[], Collections_IComparer(T) *comparer); \
	public static_ void space_T(System_Array,Sort3,T)(Ti array[], System_Comparison(T) comparison); \
	public static_ void space_T(System_Array,Sort4,T)(Ti array[], int_ index, int_ length); \
	public static_ void space_T(System_Array,Sort5,T)(Ti array[], int_ index, int_ length, Collections_IComparer(T) *comparer);
#define Implement_System_Array_Sort(T, Ti) \
	/*[ Sort<T> ] */ \
	public static_ void space_T(System_Array,Sort,T)(Ti array[]) \
	{ \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		space_T(System_Array,Sort5,T)(array, 0, array_getLength(array), (Collections_IComparer(T) *)null); \
	} \
	/*[ Sort2<T> ] */ \
	public static_ void space_T(System_Array,Sort2,T)(Ti array[], Collections_IComparer(T) *comparer) \
	{ \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		space_T(System_Array,Sort5,T)(array, 0, array_getLength(array), comparer); \
	} \
	/*[ Sort3<T> ] */ \
	public static_ void space_T(System_Array,Sort3,T)(Ti array[], System_Comparison(T) comparison) \
	{ \
		Collections_IComparer(T) *comparer; \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		if (comparison == null) \
		{ \
			throw(ArgumentNullException, L"comparison"); \
		} \
		comparer = asNew(Collections_IComparer(T),,System_ArrayXFunctorComparer(T),comparison); \
		space_T(System_Array,Sort2,T)(array, comparer); \
	} \
	/*[ Sort4<T> ] */ \
	public static_ void space_T(System_Array,Sort4,T)(Ti array[], int_ index, int_ length) \
	{ \
		space_T(System_Array,Sort5,T)(array, index, length, (Collections_IComparer(T) *)null); \
	} \
	/*[ Sort5<T> ] */ \
	public static_ void space_T(System_Array,Sort5,T)(Ti array[], int_ index, int_ length, Collections_IComparer(T) *comparer) \
	{ \
		Collections_IComparer(T) *defaultComparer; \
		if (array == null) \
		{ \
			throw(ArgumentNullException, L"array"); \
		} \
		if ((index < 0) || (length < 0)) \
		{ \
			throw(ArgumentOutOfRangeException, (length < 0 ? L"length" : L"index")); \
		} \
		if ((array_getLength(array) - index) < length) \
		{ \
			throw(ArgumentException, L"Argument_InvalidOffLen"); \
		} \
		defaultComparer = as(getsT(Collections_Comparer,T,Default), Collections_IComparer(T)); \
		if ((length > 1) && (((comparer != null) && (comparer != defaultComparer)) || (TrySZSort(array, null, index, (index + length) - 1) == false))) \
		{ \
			/*ArraySortHelper<T>.Default.Sort(array, index, length, comparer);*/ \
		} \
	}


///<summary>
/// Sort<TKey, TValue>
///</summary>
#define Declare_System_Array_Sort2(TKey, TValue, TiKey, TiValue) \
	/* Forward-declare */ \
	public static_ void space_T(System_Array,Sort,TKey##TValue)(TKey keys[], TValue items[]); \
	public static_ void space_T(System_Array,Sort2,TKey##TValue)(TKey keys[], TValue items[], Collections_IComparer(TKey) *comparer); \
	public static_ void space_T(System_Array,Sort3,TKey##TValue)(TKey keys[], TValue items[], int_ index, int_ length); \
	public static_ void space_T(System_Array,Sort4,TKey##TValue)(TKey keys[], TValue items[], int_ index, int_ length, Collections_IComparer(TKey) *comparer);
#define Implement_System_Array_Sort2(TKey, TValue, TiKey, TiValue) \
	/*[ Sort<TKey, TValue> ] */ \
	public static_ void space_T(System_Array,Sort,TKey##TValue)(TKey keys[], TValue items[]) \
	{ \
		if (keys == null) \
		{ \
			throw(ArgumentNullException, L"keys"); \
		} \
		space_T(System_Array,Sort4,TKey##TValue)(keys, items, 0, array_getLength(keys), null); \
	} \
	/*[ Sort2<TKey, TValue> ] */ \
	public static_ void space_T(System_Array,Sort2,TKey##TValue)(TKey keys[], TValue items[], Collections_IComparer(TKey) *comparer) \
	{ \
		if (keys == null) \
		{ \
			throw(ArgumentNullException, L"keys"); \
		} \
		space_T(System_Array,Sort4,TKey##TValue)(keys, items, 0, array_getLength(keys), comparer); \
	} \
	/*[ Sort3<TKey, TValue> ] */ \
	public static_ void space_T(System_Array,Sort3,TKey##TValue)(TKey keys[], TValue items[], int_ index, int_ length) \
	{ \
		space_T(System_Array,Sort4,TKey##TValue)(keys, items, index, length, null); \
	} \
	/*[ Sort4<TKey, TValue> ] */ \
	public static_ void space_T(System_Array,Sort4,TKey##TValue)(TKey keys[], TValue items[], int_ index, int_ length, Collections_IComparer(TKey) *comparer) \
	{ \
		if (keys == null) \
		{ \
			throw(ArgumentNullException, L"keys"); \
		} \
		if ((index < 0) || (length < 0)) \
		{ \
			throw(ArgumentOutOfRangeException, (length < 0 ? L"length" : L"index")); \
		} \
		if (((keys.Length - index) < length) || ((items != null) && (index > (items.Length - length)))) \
		{ \
			throw(ArgumentException, L"Argument_InvalidOffLen"); \
		} \
		Collections_IComparer(T) *defaultComparer = getsT(Collections_Comparer,TKey,Default); \
		if ((length > 1) && (((comparer != null) && (comparer != defaultComparer)) || (TrySZSort(keys, items, index, (index + length) - 1) == false))) \
		{ \
			/*ArraySortHelper<TKey, TValue>.Default.Sort(keys, items, index, length, comparer);*/ \
		} \
	}

#endif /* __System_Array_H__ */
